package com.jinzhi.jzweb.service.impl.moduleConfig;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.utils.Result;
import com.jinzhi.common.utils.StringUtil;
import com.jinzhi.jzweb.domain.StuSignUpComDO;
import com.jinzhi.jzweb.domain.moduleConfig.CareStuSignUpComRealityDO;
import com.jinzhi.jzweb.domain.moduleConfig.TrackDrawDO;
import com.jinzhi.jzweb.pojo.TrainingAgencyPageVo;
import com.jinzhi.jzweb.pojo.moduleConfig.DecryptNumVO;
import com.jinzhi.jzweb.pojo.moduleConfig.TrackDto;
import com.jinzhi.jzweb.service.StuSignUpComService;
import com.jinzhi.jzweb.service.moduleConfig.CareStuSignUpComRealityService;
import com.jinzhi.jzweb.service.moduleConfig.TrackDrawService;
import com.jinzhi.jzweb.utils.EasyPoiUtil;
import io.swagger.models.auth.In;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jinzhi.jzweb.dao.TrackDrawDao;
import com.jinzhi.common.base.CoreServiceImpl;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 赛道抽签表（存储抽签信息）
 * </pre>
 * <small> 2024-02-28 09:32:18 | lance</small>
 */
@Service
public class TrackDrawServiceImpl extends CoreServiceImpl<TrackDrawDao, TrackDrawDO> implements TrackDrawService {

    @Autowired
    private StuSignUpComService stuSignUpComService;

    @Autowired
    private CareStuSignUpComRealityService careStuSignUpComRealityService;


    //存储处理完后的学校信息
    private List<StuSignUpComDO> distinctStuSignUpComDOS;

    /**
     * 领队抽签 需要分页
     *
     * 对每个院校进行检录号抽签
     *
     *
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Result<Page<TrackDrawDO>> trackDrawList(TrackDrawDO trackDrawDTO) {
        //查询总条数
        LinkedList<String> numList = new LinkedList<>();
        int i = this.selectCount(new EntityWrapper<TrackDrawDO>());
        for (int j = 1; j <= i; j++) {
            numList.add(String.valueOf(j));
        }

        //把需要固定的检录号先从检录号列表中移除
        List<TrackDrawDO> trackDrawDOS1 = this.selectList(new EntityWrapper<TrackDrawDO>().isNotNull("place_num"));
        if(null!=trackDrawDOS1 && !trackDrawDOS1.isEmpty()){
            for (TrackDrawDO trackDrawDO : trackDrawDOS1) {
                numList.remove(trackDrawDO.getPlaceNum());
            }
        }

        //查询已经抽签的检录号 并且删除已经抽完的检录号
        List<TrackDrawDO> trackDrawDOS = this.selectList(new EntityWrapper<TrackDrawDO>().isNotNull("record_number"));
        if(null!=trackDrawDOS && !trackDrawDOS.isEmpty()){
            for (TrackDrawDO trackDrawDO : trackDrawDOS) {
                numList.remove(trackDrawDO.getRecordNumber());
            }
        }

        //查询当前页参赛选手信息 这里需要重复抽签 则当前页的检录号可以重复抽
        Page<TrackDrawDO> page = new Page<TrackDrawDO>(trackDrawDTO.getPageNumber(),trackDrawDTO.getPageSize());
        Wrapper<TrackDrawDO> entityWrapper =new EntityWrapper<TrackDrawDO>();
        entityWrapper.orderBy(true,"sort");
        Page<TrackDrawDO> pages = this.selectPage(page, entityWrapper);
        List<TrackDrawDO> records = pages.getRecords();

        //当前页的检录号重新放到抽签的列表中
        if(null!=records.get(0).getRecordNumber()){
            for (TrackDrawDO record : records) {
                numList.add(String.valueOf(record.getRecordNumber()));
            }

        }
        //打乱一下存放检录号的列表
        Random random = new Random();
        Collections.shuffle(numList,random);
        for (TrackDrawDO record : records) {
            if(null!=record.getPlaceNum()){
                record.setRecordNumber(record.getPlaceNum());
                numList.remove(record.getPlaceNum());
            }else{
                record.setRecordNumber(numList.getFirst());
                numList.removeFirst();
            }
            //检录号同步到真实的选手管理表
            CareStuSignUpComRealityDO careStuSignUpComRealityDO = new CareStuSignUpComRealityDO();
            careStuSignUpComRealityDO.setRecordNumber(record.getRecordNumber());
            careStuSignUpComRealityService.update(careStuSignUpComRealityDO,new EntityWrapper<CareStuSignUpComRealityDO>().eq("unit_name",record.getUnitName()));
            //同步到虚拟表
            StuSignUpComDO stuSignUpComDO = new StuSignUpComDO();
            stuSignUpComDO.setRecordNumber(record.getRecordNumber());
            stuSignUpComService.update(stuSignUpComDO,new EntityWrapper<StuSignUpComDO>().eq("unit_name",record.getUnitName()));

        }
        this.updateBatchById(records);
        records.get(0).setHasDraw(true);
        records.get(0).setTotal(pages.getTotal());
        pages.setRecords(records);
        return Result.ok(pages);
    }

    /**
     * 查询上一次的抽签结果
     * @param trackDrawDTO
     * @return
     */
    @Override
    public Page<TrackDrawDO> trackList(TrackDrawDO trackDrawDTO) {
        Page<TrackDrawDO> page = new Page<TrackDrawDO>(trackDrawDTO.getPageNumber(), trackDrawDTO.getPageSize());
        //存储抽签你信息
        boolean hasDraw = true;//默认为true.不存在上次抽签结果时改为false

        //查询上一次的抽签结果
        Wrapper<TrackDrawDO> wrapper = new EntityWrapper<>();
        wrapper.orderBy(true,"sort");
        Page<TrackDrawDO> trackDrawDOPage = this.selectPage(page, wrapper);
        List<TrackDrawDO> trackDrawDOS = trackDrawDOPage.getRecords();

        //如果没有抽签上一次抽签结果那就默认初始化
        if(trackDrawDOS==null || trackDrawDOS.size()==0){
            hasDraw = false;
            Wrapper<CareStuSignUpComRealityDO> entityWrapper =new EntityWrapper<>();
            List<CareStuSignUpComRealityDO> stuSignUpComDOS = careStuSignUpComRealityService.selectList(entityWrapper);
            List<CareStuSignUpComRealityDO> distinctStuSignUpComDOS = stuSignUpComDOS.stream()
                    .collect(Collectors.toMap(CareStuSignUpComRealityDO::getUnitName, s -> s, (s1, s2) -> {
                        // 如果placeNum不为空，优先保留具有非空placeNum的对象
                        if (s1.getPlaceNum() != null && !s1.getPlaceNum().isEmpty()) {
                            return s1;
                        } else {
                            return s2;
                        }
                    }))
                    .values()
                    .stream()
                    .sorted(Comparator.comparing(CareStuSignUpComRealityDO::getPlaceNum, Comparator.nullsLast(Comparator.naturalOrder())))
                    .collect(Collectors.toList());
            int i=0;
            for (CareStuSignUpComRealityDO stuSignUpComDO : distinctStuSignUpComDOS) {
                TrackDrawDO trackDrawDO = new TrackDrawDO();
                BeanUtils.copyProperties(stuSignUpComDO,trackDrawDO);
                trackDrawDO.setSort(i+=1);
                trackDrawDOS.add(trackDrawDO);
            }
            this.insertBatch(trackDrawDOS);

            Wrapper<TrackDrawDO> wrapper2 = new EntityWrapper<>();
            wrapper.orderBy(true,"sort");
            Page<TrackDrawDO> trackDrawDOPage1 = this.selectPage(page, wrapper2);
            trackDrawDOPage1.getRecords().get(0).setHasDraw(hasDraw);
            trackDrawDOPage1.getRecords().get(0).setTotal(trackDrawDOPage1.getTotal());
            return trackDrawDOPage1;

        }
        trackDrawDOS.get(0).setHasDraw(hasDraw);
        trackDrawDOS.get(0).setTotal(trackDrawDOPage.getTotal());
        trackDrawDOPage.setRecords(trackDrawDOS);

        return trackDrawDOPage;
    }

    @Override
    public Result getTrack(Integer current, Integer size) {
        //分组查询团队信息
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(current, size);
        Page<CareStuSignUpComRealityDO>  selectPage = careStuSignUpComRealityService.selectPage(page,new EntityWrapper<CareStuSignUpComRealityDO>().groupBy("unit_name").orderBy(false,"record_number"));
        if(selectPage.getRecords().isEmpty()){
            return Result.ok(selectPage);
        }
        List<String> uNames = selectPage.getRecords().stream().map(CareStuSignUpComRealityDO::getUnitName).collect(Collectors.toList());
        //根据团队名称查询选手信息
        List<CareStuSignUpComRealityDO> comRealityDOS = careStuSignUpComRealityService.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().in("unit_name",uNames));
        if(comRealityDOS.isEmpty()){
            return Result.ok(selectPage);
        }
        //把选手信息归属与团队
        selectPage.getRecords().forEach(a -> {
            a.setComRealityDOS(comRealityDOS.stream().filter(b-> a.getUnitName().equals(b.getUnitName())).collect(Collectors.toList()));
        });
        return Result.ok(selectPage);
    }

    @Override
    public Result trackDraw1(Integer current, Integer size) {
        String[] filed = {"B1","B2","B3"};
        //查询所有团队信息
        List<CareStuSignUpComRealityDO> team = careStuSignUpComRealityService.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().groupBy("unit_name"));

        //分组查询团队信息
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(current, size);
        Page<CareStuSignUpComRealityDO>  selectPage = careStuSignUpComRealityService.selectPage(page,new EntityWrapper<CareStuSignUpComRealityDO>().isNull("track_draw").groupBy("unit_name"));
        if(selectPage.getRecords().isEmpty()){
            return Result.fail("没有团队信息");
        }
        List<String> uNames = selectPage.getRecords().stream().map(CareStuSignUpComRealityDO::getUnitName).collect(Collectors.toList());
        //根据团队名称查询选手信息
        List<CareStuSignUpComRealityDO> comRealityDOS = careStuSignUpComRealityService.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().in("unit_name",uNames));
        if(comRealityDOS.isEmpty()){
            return Result.fail("没有相应的选手信息");
        }
        //把选手信息归属与团队
        selectPage.getRecords().forEach(a -> {
            a.setComRealityDOS(comRealityDOS.stream().filter(b-> a.getUnitName().equals(b.getUnitName())).collect(Collectors.toList()));
        }) ;
        //生成等于团队数量的随机数字
        int track = 0;
        for (int i = 0; i < selectPage.getRecords().size(); i++) {
            track = (int)(Math.random()*(team.size()-1+1)+1);
            //检录号如果不是唯一重新生成
            Integer finalTrack = track;
            //效验检录号是否重复
            List<CareStuSignUpComRealityDO> recordNumbers =  careStuSignUpComRealityService.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().eq("record_number",finalTrack));
            if(!recordNumbers.isEmpty()){
                i--;
                continue;
            }
            //赋值检录号,抽取赛场,赋值赛场
            if(selectPage.getRecords().get(i).getComRealityDOS().size()==3) {
                for (int j = 0; j < selectPage.getRecords().get(i).getComRealityDOS().size(); j++) {
                    int filedMath = (int) (Math.random() * (filed.length - 1 + 1) + 0);
                    //验证团队中赛场是否重复
                    List<CareStuSignUpComRealityDO> recordFiled = selectPage.getRecords().get(i).getComRealityDOS().stream().filter(a -> Objects.equals(filed[filedMath], a.getField())).collect(Collectors.toList());
                    if (!recordFiled.isEmpty()) {
                        j--;
                        continue;
                    }
                    selectPage.getRecords().get(i).getComRealityDOS().get(j).setRecordNumber(finalTrack.toString());
                    selectPage.getRecords().get(i).getComRealityDOS().get(j).setField(filed[filedMath]);
                }
                //同步虚拟表信息
                StuSignUpComDO stu = new StuSignUpComDO();
                stu.setRecordNumber(finalTrack.toString());
                stuSignUpComService.update(stu,new EntityWrapper<StuSignUpComDO>().eq("unit_name",selectPage.getRecords().get(i).getUnitName()));
                careStuSignUpComRealityService.updateBatchById(selectPage.getRecords().get(i).getComRealityDOS());
            }
        }

        return Result.ok();

    }

    /**
     * 开始抽签  上饶抽签
     * @param current
     * @param size
     * @return
     */
    @Override
    public Result trackDraw(Integer current, Integer size) {
        String[] filed = {"B1","B2","B3"};

        //分组查询团队信息
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(current, size);
        Page<CareStuSignUpComRealityDO>  selectPage = careStuSignUpComRealityService.selectPage(page,new EntityWrapper<CareStuSignUpComRealityDO>().orderBy("id",false));
        if(selectPage.getRecords().isEmpty()){
            return Result.fail("没有团队信息");
        }

        Map<String, List<CareStuSignUpComRealityDO>> map = selectPage.getRecords().stream()
                .collect(Collectors.groupingBy(CareStuSignUpComRealityDO::getUnitName));
        // 将固定的学校过滤出来
        Map<String, List<CareStuSignUpComRealityDO>> map1 = selectPage.getRecords().stream()
                .filter(record -> record.getPlaceNum() != null && !record.getPlaceNum().isEmpty()) // 过滤出 placeNum 不为空的数据
                .collect(Collectors.groupingBy(CareStuSignUpComRealityDO::getUnitName)); // 按照 unitName 进行分组

        //生成等于团队数量的随机数字
        List<String> num = new ArrayList<>();
        for (int i = 1; i <= map.size(); i++) {
            num.add(i+"");
        }
        Random random = new Random();
        Collections.shuffle(num, random); // 打乱检录号

        for (List<CareStuSignUpComRealityDO> student1 : map1.values()) {
            if (StringUtil.notEmpty(student1.get(0).getPlaceNum())){
                num.remove(student1.get(0).getPlaceNum());
                break;
            }
        }

        for (List<CareStuSignUpComRealityDO> students : map.values()) {
            List<String> list = new ArrayList<>();
            for (int t = 0; t < filed.length; t++) {
                list.add(filed[t]);
            }
            Collections.shuffle(list, random); // 打乱检录号
            if (students.size() == 3) {
                if (StringUtil.notEmpty(students.get(0).getPlaceNum())){
                    students.get(0).setRecordNumber(students.get(0).getPlaceNum());
                    students.get(1).setRecordNumber(students.get(0).getPlaceNum());
                    students.get(2).setRecordNumber(students.get(0).getPlaceNum());
                    num.remove(students.get(0).getPlaceNum());
                }else {
                    students.get(0).setRecordNumber(num.get(0));
                    students.get(1).setRecordNumber(num.get(0));
                    students.get(2).setRecordNumber(num.get(0));
                    num.remove(num.get(0));
                }
                assignTrackDraw(students.get(0),list);
                assignTrackDraw(students.get(1),list);
                assignTrackDraw(students.get(2),list);
            }

        }
        careStuSignUpComRealityService.updateBatchById(selectPage.getRecords());

        return Result.ok();

    }

    /**
     * 判断检录序号是否固定，没固定的话就从队列中取一个
     * @param student
     * @param list
     */
    private void assignTrackDraw(CareStuSignUpComRealityDO student, List<String> list) {
        if (StringUtil.notEmpty(student.getTrackDraw2())) {
            student.setField(student.getTrackDraw2());
            list.remove(student.getTrackDraw2());
        } else {
            student.setField(list.get(0));
            list.remove(list.get(0));
        }
    }



    @Override
    public void downloadImportTrackDraw(HttpServletResponse response, Integer current, Integer size) {
        List<TrackDto>  trackDtos = new ArrayList<>();
        //分页分组查询团队信息
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(current, size);
        Page<CareStuSignUpComRealityDO>  selectPage = careStuSignUpComRealityService.selectPage(page,new EntityWrapper<CareStuSignUpComRealityDO>().groupBy("unit_name"));
        List<String> uNames = selectPage.getRecords().stream().map(CareStuSignUpComRealityDO::getUnitName).collect(Collectors.toList());
        //根据团队名称查询选手信息
        List<CareStuSignUpComRealityDO> comRealityDOS = careStuSignUpComRealityService.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().in("unit_name",uNames));
        //把选手信息归属与团队
        selectPage.getRecords().forEach(a -> {
            TrackDto dto = new TrackDto();
            a.setComRealityDOS(comRealityDOS.stream().filter(b-> a.getUnitName().equals(b.getUnitName())).collect(Collectors.toList()));
            //赋值导出类
            dto.setRecordNumber(Integer.parseInt(a.getRecordNumber()));
            dto.setUnitName(a.getUnitName());
            dto.setField1(setField(a.getComRealityDOS().get(0).getField()));
            dto.setField2(setField(a.getComRealityDOS().get(1).getField()));
            dto.setField3(setField(a.getComRealityDOS().get(2).getField()));
            dto.setName1(setField(a.getComRealityDOS().get(0).getName()));
            dto.setName2(setField(a.getComRealityDOS().get(1).getName()));
            dto.setName3(setField(a.getComRealityDOS().get(2).getName()));
            trackDtos.add(dto);
        });
        List<TrackDto> trackDtox = trackDtos.stream().filter(a -> Objects.nonNull(a.getRecordNumber())).sorted(Comparator.comparingInt(TrackDto::getRecordNumber)).collect(Collectors.toList());
        EasyPoiUtil.exportExcel(trackDtox, "抽签导出", "抽签导出", TrackDto.class, "抽签导出", response);
    }

    private String setField(String field){
        if("B1".equals(field)){
            field = "B";
        }else if("B2".equals(field)){
            field = "C";
        }else if("B3".equals(field)){
            field = "D";
        }
        return field;
    }

}


